use std::{
    fs::File,
    io::Read,
    path::{Path, PathBuf},
};

use dj::Expr;

fn main() -> std::io::Result<()> {
    let files = enumerate_files()?;

    println!("Select a DJ program to visit(index): ");

    let mut file_index = String::new();
    std::io::stdin().read_line(&mut file_index)?;
    let idx: usize = file_index.trim_end().parse().unwrap();

    match Expr::try_from(read_file(&files[idx])?.as_str()) {
        Ok(expr) => {
            expr.visit(|e: &Expr, compound_idx| {
                match e {
                    dj::Expr::Compound(_) => {
                        print!("Compound");
                    }
                    dj::Expr::Literal(lit) => {
                        print!("Literal: {:?}", lit)
                    }
                    dj::Expr::Ident(id) => {
                        print!("Identifier: {}", id)
                    }
                    dj::Expr::List(list) => {
                        print!("List: {:?}", list)
                    }
                    _ => (),
                }

                if let Some(idx) = compound_idx {
                    print!("({})", idx)
                }

                println!()
            });
        }
        Err(err) => {
            println!("Error on parsing: {err:?}");
        }
    }

    Ok(())
}

fn enumerate_files() -> std::io::Result<Vec<PathBuf>> {
    let cur = std::env::current_dir()?.join("examples");

    let ans: Vec<PathBuf> = std::fs::read_dir(cur)?
        .filter(|entry| {
            if let Ok(entry) = entry {
                return entry.path().extension().unwrap() == "dj";
            }
            false
        })
        .map(|entry| entry.unwrap().path())
        .collect();

    for (idx, path) in ans.iter().enumerate() {
        println!("{}:{:?}", idx, path.file_name().unwrap());
    }

    Ok(ans)
}

fn read_file<P: AsRef<Path>>(path: P) -> Result<String, std::io::Error> {
    let mut src_file = File::open(path)?;
    let mut src = String::new();
    src_file.read_to_string(&mut src)?;
    Ok(src)
}
